/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tomasio.projects.lua.dao;

import com.tomasio.projects.lua.exception.DAOException;
import com.tomasio.projects.lua.model.Application;
import java.util.List;
import javax.naming.Name;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.support.LdapNameBuilder;

/**
 *
 * @author fernandofot
 */
public class SpringLDAPApplicationDAO implements ApplicationDAO {

    public static final String BASE_DN = "dc=decea,dc=intraer";

    private LdapTemplate ldapTemplate;

    public void setLdapTemplate(LdapTemplate ldapTemplate) {
        this.ldapTemplate = ldapTemplate;
    }

    @Override
    public String create(Application application) throws DAOException {
        DirContextAdapter context = new DirContextAdapter(buildDn(application));
        mapToContext(application, context);
        ldapTemplate.bind(context);
        return application.getUid();
    }

    @Override
    public void remove(String uid) throws DAOException {
        Application application = find(uid);
        ldapTemplate.unbind(buildDn(application));
    }

    @Override
    public void update(Application application) throws DAOException {
        Name dn = buildDn(application);
        DirContextOperations context = ldapTemplate.lookupContext(dn);
        mapToContext(application, context);
        ldapTemplate.modifyAttributes(context);
    }

    @Override
    public List<Application> findAll() throws DAOException {
        EqualsFilter filter = new EqualsFilter("objectclass", "organizationalUnit");
        Name applicationsPath = LdapNameBuilder.newInstance()
                .add("ou", "groups")
                .build();
        return ldapTemplate.search(applicationsPath, filter.encode(), getContextMapper());

    }

    @Override
    public List<Application> search(String term) throws DAOException {
        EqualsFilter filter = new EqualsFilter("objectclass", "organizationalUnit");
        Name applicationsPath = LdapNameBuilder.newInstance()
                .add("ou", "groups")
                .build();
        return ldapTemplate.search(applicationsPath, filter.encode(), getContextMapper());
    }

    @Override
    public Application find(String uid) throws DAOException {
        Name dn = buildDn(uid);
        return (Application) ldapTemplate.lookup(dn, getContextMapper());
    }

    protected ContextMapper getContextMapper() {
        return new ApplicationContextMapper();
    }

    protected Name buildDn(Application application) {
        return buildDn(application.getName());
    }

    protected Name buildDn(String name) {
        return LdapNameBuilder.newInstance()
                .add("ou", "groups")
                .add("ou", name)
                .build();
    }

    protected void mapToContext(Application application, DirContextOperations context) {
        context.setAttributeValues("objectclass", new String[]{"top", "organizationalUnit"});
        context.setAttributeValue("ou", application.getName());

    }

    private static class ApplicationContextMapper extends AbstractContextMapper<Application> {

        @Override
        public Application doMapFromContext(DirContextOperations context) {
            Application a = new Application();
            a.setUid(context.getStringAttribute("ou"));
            a.setName(context.getStringAttribute("ou"));
            a.setDescription(context.getStringAttribute("ou"));
            return a;
        }

    }

}
